<template>
  <div id="container">
    <div class="column-header">
        <span style="margin-left: 50px;color: #515a6e;cursor: pointer">
          建筑：{{ buildingName }}
        </span>
      <div class="btns">
        <!--楼层选择-->
        <a-select
            ref="select"
            :value="floor.name"
            :disabled="historyLoading"
            style="width: 100px;height:40px;background:transparent;margin-right: 30px"
            @change="handleChange">
          <a-select-option v-for="(floorItem) in floors" v-bind:key="floorItem.id" :value="floorItem.id">
            {{
              floorItem.name
            }}
          </a-select-option>
        </a-select>
      </div>
    </div>
    <div ref="mapContainer" class="content"></div>
  </div>
</template>

<script>
import moment from 'moment';
import * as zymap from '../zymap.min.js'
import {METHOD, request} from "@/utils/request";
import {ERECT, HISTORY_MAP, INIT_MAP, MAP_INFORMATION} from "@/services/api";
import {HEAT_MAP, MAP_POINTS} from "../services/api";

export default {
  name: "routeMap",
  data() {
    return {
      demo: -1,
      historyLoading: false,//查看历史loading
      ws: null,//长链接
      zymap: null,
      pointData: [],//路径
      pointLines: [],//路径实例
      userColors: [],//用户路径使用的颜色
      currentPattern: 0,//当前模式，0-，1-历史
      buildingName: '',//建筑名称
      floors: [],//楼层
      floor: {},//默认楼层
      genders: [{
        label: '男', value: 0
      }, {
        label: '女', value: 1
      }],//性别
      ages: [{
        label: '少年', value: 0
      }, {
        label: '青年', value: 1
      }, {
        label: '资深青年', value: 2
      }, {
        label: '中年', value: 3
      }, {
        label: '老年', value: 4
      }],//年纪
      timeType: [{
        label: '日', value: 1
      }, {
        label: '周', value: 2
      }, {
        label: '月', value: 3
      }],//模式
      paramsTime: {
        timeType: 1,
        days: [moment(moment().subtract(0, "days").format("YYYY-MM-DD")),
          moment(moment().subtract(0, "days").format("YYYY-MM-DD"))],
        weeks: [moment(moment().subtract(2, "weeks").format("YYYY-MM-DD")),
          moment(moment().subtract(1, "weeks").format("YYYY-MM-DD"))],
        months: [moment(moment().subtract(2, "months").format("YYYY-MM-DD")),
          moment(moment().subtract(1, "months").format("YYYY-MM-DD"))]
      },
      checkGender: [0, 1],//已选性别
      selectGender: [0, 1],
      checkAge: [0, 1, 2, 3, 4],//已选年纪
      selectAge: [0, 1, 2, 3, 4],
      selectTime: '',
      colors: ['#ffc53d', '#ffec3d', '#ffec3d', '#73d13d', '#36cfc9', '#40a9ff', '#597ef7', '#9254de', '#f759ab'],//路径颜色
      historyVisible: false,
      endOpen: false,
      heatmap: null,//热力实例
      mapPoints: [],//路网数据
      mapPaths: [],//路网路径
      maxCount: 0,//热力最大值
      minCount: 0,//热力最小值
      interval:null,
    }
  },
  // components:{DownOutlined},
  mounted() {
    this.selectTime = `${this.paramsTime.days[0].format('YYYY-MM-DD')} 至 ${this.paramsTime.days[1].format('YYYY-MM-DD')}`
    this.$nextTick(() => {
      this.getMapInformation()
      this.getErect()
    })
  },

  methods: {
    disabledStartDate(startValue) {
      const endValue = this.endValue;
      if (!startValue || !endValue) {
        return false;
      }
      return startValue.valueOf() > endValue.valueOf();
    },
    disabledEndDate(endValue) {
      const startValue = this.startValue;
      if (!endValue || !startValue) {
        return false;
      }
      return startValue.valueOf() >= endValue.valueOf();
    },
    handleStartOpenChange(open) {
      if (!open) {
        this.endOpen = true;
      }
    },
    handleEndOpenChange(open) {
      this.endOpen = open;
    },
    selectMonthChange(value) {
      this.paramsTime.months=value
    },
    selectMonthPanelChange(value, mode) {
      this.paramsTime.months=value
    },
    /**
     * 日期选择发生变化
     */
    onChange(date, dateString) {
      console.log(date, dateString);
      this.paramsTime.days=date
    },
    /**
     * 获取年龄
     */
    getAge(type) {
      switch (type) {
        case 0:
          return '少年';
        case 1:
          return '青年';
        case 2:
          return '资深青年';
        case 3:
          return '中年';
        case 4:
          return '老年';
      }

    },

    /**
     * 楼层切换
     **/
    handleChange(value) {
      //根据楼层id匹配对应楼层数据
      for (let i = 0; i < this.floors.length; i++) {
        const floor = this.floors[i]
        if (floor.id === value && this.floor.id !== value) {
          this.floor = floor
          if (this.zymap !== null) {
            //切换楼层
            this.zymap.changeFloor(floor.code)
          }
          break;
        }
      }
    },
    onUnitClick(unit) {
      alert(unit.name || unit.id)
    },
    /**
     * 初始化地图
     */
    initMap() {
      let floor = this.floor
      if (floor.buildingCode && floor.code) {
        //初始化地图
        this.zymap = new zymap.ZYMap({
          serverUrl: 'http://map.malllead.com',
          appId: '10010001',
          appSecret: '4c4jujUBYYs5elZluj42vrVKtuTO9scw',
          buildingCode: floor.buildingCode,
          container: this.$refs.mapContainer,
          floorCode: floor.code,
          viewMode: '2d'
        })
        const ui = new zymap.ZYUI({
          compass: 1, // 指南针 0=不显示 1=显示
          viewMode: 1, // 2d-3d切换
          lang: 0, // 语言切换
          zoom: 1, // 放大缩小
          floor: 0, // 楼层控件
          multiMode: 0 // 单层 多层模式
        })
        ui.addToMap(this.zymap)

        this.zymap.on('floorChanged', this.afterFloorChange.bind(this))
      }

    },
    /**
     * 楼层切换监听
     */
    afterFloorChange() {
      // this.cleanMapPoints()
      if (this.interval!==null){
        clearInterval(this.interval)
      }
      this.getMapPoints()
    },

    /**
     * 获取地图基础信息
     */
    getMapInformation() {
      request(MAP_INFORMATION, METHOD.GET, {})
          .then(res => {
            console.log('地图信息', res)
            const data = res.data
            if (data !== null && data.code === 0 && data.data !== null && data.data.length > 0) {
              this.floors = data.data
              this.floor = data.data[0]
              this.initMap()
            }
          })
    },
    getMapPoints() {
      request(MAP_POINTS + `/${this.floor.buildingCode}/${this.floor.code}`, METHOD.GET, {})
          .then(res => {
            console.log('路网数据', res)
            if (res.data.code === 0 && res.data.data !== null) {
              this.mapPoints = res.data.data.points
              this.mapPaths = res.data.data.paths
              this.cleanMapPoints()
              this.getHistoryData()
              this.interval=setInterval(()=>{
                this.cleanMapPoints()
                this.getHistoryData()
              },1000*60)
            }

          })
    },
    /**
     * 获取建筑信息
     */
    getErect() {
      request(ERECT, METHOD.GET, {})
          .then(res => {
            console.log('建筑信息', res)
            const data = res.data
            if (data !== null && data.data !== null) {
              const name = data.data.name
              console.log('建筑名称', name)
              this.buildingName = name
            }
          })
    },

    /**
     * 添加路径
     * @param data
     */
    initMapHeat(data) {
      console.log('initMapHeat-map',this.zymap,'mapPoints',this.mapPoints)
      const heatmap = new zymap.ZYHeatMap({
        radius: 80, // 点的半径，越大表示热力点面积越大，单位是像素
        min: 0, // 数值范围的最小值
        max: this.maxCount, // data中value数值范围的最大值， 100会渲染成红色
        blur: 0.85, // 边缘模糊度，越大边缘模糊半径越大。
        height: this.minCount // 图层在地图中的高度
      })
      heatmap.setData(this.mapPoints)
      this.heatmap = heatmap
      heatmap.addTo(this.zymap)

    },

    /**
     * 查询历史数据
     */
    searchHistoryData() {
      this.selectGender = this.checkGender
      this.selectAge = this.checkAge
      const timeParams = this.paramsTime
      //时间类型，1-日，2-周，3-月
      const timeType = timeParams.timeType

      if (timeType === 1) {
        this.selectTime = `${timeParams.days[0].format('YYYY-MM-DD')} 至 ${timeParams.days[1].format('YYYY-MM-DD')}`
      } else if (timeType === 2) {
        this.selectTime = `${timeParams.weeks[0].format('YYYY-ww')}周 至 ${timeParams.weeks[1].format('YYYY-ww')}周`
      } else if (timeType === 3) {
        this.selectTime = `${timeParams.months[0].format('YYYY-MM')} 至 ${timeParams.months[1].format('YYYY-MM')}`
      }
      this.cleanMapPoints()
      this.historyVisible = false
      this.interval=setInterval(()=>{
        this.cleanMapPoints()
        this.getHistoryData()
      },1000*60)
    },
    /**
     * 获取历史数据
     */
    getHistoryData() {
      this.historyLoading = true
      const timeParams = this.paramsTime
      //时间类型，1-日，2-周，3-月
      const timeType = timeParams.timeType
      let startTime=''
      let endTime=''
      if (timeType === 1) {
        startTime=timeParams.days[0].format('YYYY-MM-DD')
        endTime=timeParams.days[1].format('YYYY-MM-DD')
      } else if (timeType === 2) {
        startTime=timeParams.weeks[0].format('YYYY-ww')
        endTime=timeParams.weeks[1].format('YYYY-ww')
      } else if (timeType === 3) {
        startTime=timeParams.months[0].format('YYYY-MM')
        endTime=timeParams.months[1].format('YYYY-MM')
      }
      const params = {
        ageList: this.checkAge,
        nodeCode: this.floor.code,
        periodType: this.paramsTime.timeType,
        sexList: this.checkGender,
        start: startTime,
        end: endTime
      }
      request(HEAT_MAP, METHOD.POST, params)
          .then(res => {
            if (res.data !== null && res.data.code === 0 &&
                res.data.data !== null) {
              const data = res.data.data
              this.formatMapPoints(data)
              this.initMapHeat()
            } else {
              this.$message.warn(res.data?.message)
            }
          })
          .finally(() => {
            this.historyLoading = false
          })
    },

    /**
     * 清除历史数据
     */
    cleanMapPoints() {
      this.heatmap?.remove()
      this.initMapPoints()
    },

    /**
     * 随机指定范围整数
     * @param min
     * @param max
     * @returns {number}
     */
    getRandom(min, max) {
      min = Math.ceil(min);
      max = Math.floor(max);
      return Math.floor(Math.random() * (max - min + 1)) + min;
    },
    /**
     * 时间类型切换
     * @param value
     * 0-日
     * 1-周
     * 2-月
     */
    selectTimeType(value) {
      console.log('时间类型', value)
    },
    /**
     * 根据类型获取时间
     *
     */
    getTimeParams() {
      const timeParams = this.paramsTime
      //时间类型，1-日，2-周，3-月
      const timeType = timeParams.timeType
      switch (timeType) {
        case 1:
          return timeParams.days
        case 2:
          return timeParams.weeks
        case 3:
          return timeParams.months
        default:
          return ['', '']
      }
    },
    selectStartWeek(date, dateString) {
      console.log('start-time', date, dateString);
    },
    selectEndWeek(date, dateString) {
      console.log('end-time', date, dateString);
    },
    /**
     * 更新地图热力数据
     * @param data
     */
    formatMapPoints(data) {
      if (data === null) {
        return
      }

      for (const datum of data) {
        this.setMapPointValue(datum)
      }
      //查找俩点对应得坐标

      const mapPaths = this.mapPaths
      for (const mapPath of mapPaths) {
        const start = mapPath.start
        const end = mapPath.end
        const length = mapPath.length
        const ps = this.getMapPathPoints(start, end)
        this.getPoints(ps, length)
      }
    },
    /**
     * 获取俩点之间的点集合
     */
    getPoints(points, pointsLength) {
      const startPoint = points.startPoint
      const endPoint = points.endPoint
      //新点集合
      const np = []
      pointsLength = Math.floor(Math.abs(pointsLength))
      const x1 = startPoint.x
      const y1 = startPoint.y
      const v1 = startPoint.value
      np.push({
        x: x1,
        y: y1,
        value: v1
      })
      const x2 = endPoint.x
      const y2 = endPoint.y
      const v2 = endPoint.value
      const mp = this.mapPoints
      for (let i = 0; i < pointsLength; i++) {
        const nb = {
          x: np[i].x + (x2 - x1) / pointsLength,
          y: np[i].y + (y2 - y1) / pointsLength,
          value: v1 === v2 ? v1 : np[i].value + (v2 - v1) / pointsLength
        }
        np.push(nb)
        mp.push(nb)
      }
      this.mapPoints = mp
      np.push({
        x: x2,
        y: y2
      })
      return np
    },
    /**
     * 根据ID获取对应的坐标
     */
    getMapPathPoints(start, end) {
      const mapPoints = this.mapPoints
      let startPoint, endPoint;
      for (const mapPoint of mapPoints) {
        if (mapPoint.id === start) {
          startPoint = mapPoint
        }
        if (mapPoint.id === end) {
          endPoint = mapPoint
        }
      }
      return {startPoint, endPoint}
    },
    /**
     * 修改路网热力值
     * @param datum 单点数据
     * @returns {boolean}
     */
    setMapPointValue(datum) {
      const mapPoints = this.mapPoints
      for (let i = 0; i < mapPoints.length; i++) {
        const point = mapPoints[i]
        if (point.x === datum.x && point.y === datum.y) {
          let value = point.value
          if (value === undefined || value === null) {
            value = 0
          }
          const count = value + datum.value
          if (this.maxCount < count) {
            this.maxCount = count
          }
          point.value = count
          return false;
        }
      }
    },
    initMapPoints() {
      const mapPoints = this.mapPoints
      for (const mapPoint of mapPoints) {
        mapPoint.value = 0
      }
    },

  },

  beforeDestroy() {
    this.zymap?.destroy()
    this.zymap = null
    if (this.interval!==null){
      clearInterval(this.interval)
    }

  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
html, body {
  width: 100vw;
  height: 100vh;
  padding: 0;
  margin: 0 !important;
  position: relative;
  overflow: hidden;
}

#container {
  width: 100vw;
  height: 100vh;
  position: relative;
  box-sizing: border-box;
  display: flex;
  display: -moz-flex;
  display: -ms-flex;
  display: -o-flex;
  display: -webkit-flex;
  flex-direction: column;
  -ms-flex-direction: column;
  -webkit-flex-direction: column;
  overflow: hidden;
  padding: 20px;

  .column-header {
    width: 100%;
    height: 57px;
    margin-bottom: 20px;
    padding: 15px;
    border-radius: 5px;
    background: #f8f8f8; //#1d293e
    display: flex;
    display: -moz-flex;
    display: -ms-flex;
    display: -o-flex;
    display: -webkit-flex;
    flex-direction: row;
    -ms-flex-direction: row;
    -webkit-flex-direction: row;
    align-items: center;
    justify-content: space-between;
    position: relative;

    span {
      size: 14px;
      color: #ffffff;
    }

    .btns {
      height: 100%;
      display: flex;
      display: -moz-flex;
      display: -ms-flex;
      display: -o-flex;
      display: -webkit-flex;
      flex-direction: row;
      -ms-flex-direction: row;
      -webkit-flex-direction: row;
      align-items: center;
      justify-content: center;
    }
  }

  .content {
    width: calc(100vw - 40px);
    height: 100%;
    flex-shrink: 1;
    position: relative;
    box-sizing: border-box;
  }
}

.confirm-btn {
  width: 100%;
  display: flex;
  display: -moz-flex;
  display: -ms-flex;
  display: -o-flex;
  display: -webkit-flex;
  flex-direction: row;
  -ms-flex-direction: row;
  -webkit-flex-direction: row;
  align-items: end;
  justify-content: flex-end;
}

.params {
  height: 40px;
  text-align: left;
  line-height: 40px;
  padding: 0 15px;
  border-radius: 5px;
  border: 1px solid #d9d9d9;
  color: #515a6e;
  font-size: 14px;
  cursor: pointer;

  span {
    color: #515a6e !important;
  }
}

/deep/ .ant-fullcalendar-header {
  text-align: left !important;
}

/deep/ .ant-fullcalendar-header .ant-radio-group {
  display: none !important;
}

.btns {
  /deep/ .ant-select-selection--single {
    height: 40px !important;
  }

  /deep/ .ant-select-selection__rendered {
    line-height: 40px !important;
  }

  /deep/ .ant-select-selection-selected-value {
    color: #515a6e !important;
  }

  /deep/ .ant-select-arrow {
    color: #515a6e !important;
  }

  /deep/ .ant-select-selection {
    background-color: transparent !important;
  }
}

</style>
